using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using System.IO;
using System.Net;
using System.Web;
using Rest;
using Rest.Transport;
using Rest.Service;
using Coriander.Google.Services.Authentication;

namespace Coriander.Google.Services
{
    /// <summary>
    /// See: http://code.google.com/apis/picasaweb/gdata.html#Get_Photo_Feed_Manual
    /// </summary>
    public class Picasa : GoogleServiceProxyBase
    {
        private GoogleAuthTicket authTicket = null;
        private String userName;
        private const String ServiceBaseUrl = "http://picasaweb.google.com/data/feed/api";

        /// <summary>
        /// ctor: String
        /// </summary>
        /// <param name="userName">The username for Google web albums</param>
        public Picasa(String userName)
        {
            this.userName = userName;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="email"></param>
        /// <param name="password"></param>
        private void EnsureAuthenticated(String email, String password)
        {
            if (null == authTicket)
            {
                ClientLogin clientLogin = new ClientLogin();
                authTicket = clientLogin.Authenticate(
                    ClientLoginAccountType.HostedOrGoogle.Value, email,
                    password, "lh2", "sample");
            }
        }

        /// <summary>
        /// Adds a new web album
        /// </summary>
        /// <param name="email"></param>
        /// <param name="password"></param>
        /// <param name="albumName"></param>
        /// <param name="title"></param>
        /// <param name="summary"></param>
        /// <param name="location">Geographic location</param>
        /// <param name="keywords">The tags to associate with the album</param>
        /// <returns></returns>
        public XmlDocument AddAlbum(
            String email, 
            String password,
            String albumName, 
            String title,
            String summary, 
            String location,
            String[] keywords)
        {
            EnsureAuthenticated(email, password);

            String url = String.Format(
                "http://picasaweb.google.com/data/feed/api/user/{0}",
                userName);

            RestCommand command = new RestCommand(new Uri(url), RestTransport.Post);
            command.Transport.HttpContentType = Rest.Http.HttpContentType.Atom;
            command.AllowAutoRedirect = true;

            // Redirection policy, ensure redirects keep the same HTTP method
            RestRedirectionPolicy redirectPolicy = new RestRedirectionPolicy();
            redirectPolicy.PreserveHttpTransportOnRedirect = true;
            command.RedirectionPolicy = redirectPolicy;

            // Create the atom data item
            String atomXmlText =
                "<entry xmlns='http://www.w3.org/2005/Atom' " +
                "xmlns:media='http://search.yahoo.com/mrss/' " +
                "xmlns:gphoto='http://schemas.google.com/photos/2007'>" +
                "<title type='text'>" + HttpUtility.HtmlEncode(title) + "</title>" +
                "<summary type='text'>" + HttpUtility.HtmlEncode(summary) + "</summary>" +
                "<gphoto:location>" + HttpUtility.HtmlEncode(location) + "</gphoto:location>" +
                "<gphoto:access>public</gphoto:access>" +
                "<gphoto:commentingEnabled>true</gphoto:commentingEnabled>" +
                "<gphoto:timestamp>1152255600000</gphoto:timestamp>" +
                "<media:group>" +
                "  <media:keywords>" + HttpUtility.HtmlEncode(String.Join(",", keywords)) + "</media:keywords>" +
                "</media:group>" +
                "<category scheme='http://schemas.google.com/g/2005#kind' " +
                "  term='http://schemas.google.com/photos/2007#album'></category>" +
                "</entry>";

            RestDataItem atomXml = new RestDataItem("atom-header",
                Encoding.UTF8.GetBytes(atomXmlText));

            atomXml.ContentType = "application/atom+xml";

            // Authorize
            ClientLogin.AuthorizeCommand(command, authTicket);

            command.Data.Add(atomXml);

            return Invoke(command);
        }


        /// <summary>
        /// Adds a photo to web album
        /// </summary>
        /// <remarks>
        /// See: http://code.google.com/apis/picasaweb/gdata.html#Add_Photo
        /// </remarks>
        /// <param name="email"></param>
        /// <param name="password"></param>
        /// <param name="albumName"></param>
        /// <param name="fileInfo"></param>
        /// <param name="summary"></param>
        /// <returns></returns>
        /// <exception cref="FileNotFoundException" />
        public XmlDocument AddPhoto(
            String email, String password,
            String albumName, FileInfo fileInfo,
            String summary)
        {
            EnsureAuthenticated(email, password);

            if (null == fileInfo || false == fileInfo.Exists)
            {
                throw new FileNotFoundException("No file found:" + fileInfo.FullName);
            }

            if (false == String.IsNullOrEmpty(authTicket.Auth))
            {
                String url = String.Format(
                    "http://picasaweb.google.com/data/feed/api/user/{0}/album/{1}",
                    userName, albumName);

                RestCommand command = new RestCommand(new Uri(url), RestTransport.Post);
                command.Transport.HttpContentType = Rest.Http.HttpContentType.MultipartFormData;
                command.AllowAutoRedirect = true;
                command.Transport.HttpContentType.ContentType = "multipart/related";

                // Redirection policy, ensure redirects keep the same HTTP method
                RestRedirectionPolicy redirectPolicy = new RestRedirectionPolicy();
                redirectPolicy.PreserveHttpTransportOnRedirect = true;
                command.RedirectionPolicy = redirectPolicy;

                // Create the atom data item
                // TODO: Consider parsing EXIF to populate fields
                String atomXmlText =
                    "<entry xmlns='http://www.w3.org/2005/Atom'>" +
                      "<title>" +
                      System.Web.HttpUtility.HtmlEncode(Path.GetFileName(fileInfo.FullName)) +
                      "</title>" +
                      "<summary>" + summary + "</summary>" +
                      "<category scheme='http://schemas.google.com/g/2005#kind' " +
                      "    term='http://schemas.google.com/photos/2007#photo' />" +
                    "</entry>";

                RestDataItem atomXml = new RestDataItem("atom-header",
                    Encoding.UTF8.GetBytes(atomXmlText));

                atomXml.ContentType = "application/atom+xml";

                // Authorize
                ClientLogin.AuthorizeCommand(command, authTicket);

                // Add the file
                command.Data.Add(atomXml);
                command.Data.Add("sample", fileInfo, "image/jpeg");

                return Invoke(command);
            }

            return null;
        }

        /// <summary>
        /// Gets an album of photos
        /// </summary>
        /// <remarks>
        /// Example: http://picasaweb.google.com/data/feed/api/user/ben.biddington/album/TurkeyForBlog?kind=photo
        /// </remarks>
        /// <returns>
        /// Either an XML document, or a string error message
        /// 
        /// Example:
        /// 
        ///     <feed 
        ///         xmlns='http://www.w3.org/2005/Atom' 
        ///         xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' 
        ///         xmlns:geo='http://www.w3.org/2003/01/geo/wgs84_pos' 
        ///         xmlns:media='http://search.yahoo.com/mrss/' 
        ///         xmlns:photo='http://www.pheed.com/pheed/' 
        ///         xmlns:gphoto='http://schemas.google.com/photos/2007' 
        ///         xmlns:batch='http://schemas.google.com/gdata/batch' 
        ///         xmlns:exif='http://schemas.google.com/photos/exif/2007'>
        ///         [...]
        ///     </feed>
        /// 
        /// </returns>
        public XmlDocument GetPhotos(String userName, String albumName)
        {
            String url = String.Format(
                "http://picasaweb.google.com/data/feed/api/user/{0}/album/{1}",
                userName, albumName);

            String response = null;

            RestCommand command = new RestCommand(
                new Uri(url),
                RestTransport.Get);

            command.Parameters.Add("kind", "photo");

            return Invoke(command);
        }

        /// <summary>
        /// Request a list of all albums for user
        /// </summary>
        /// <param name="userName"></param>
        /// <returns></returns>
        public XmlDocument GetAlbums(String userName)
        {
            String url = String.Format(
                "http://picasaweb.google.com/data/feed/api/user/{0}", userName);

            String response = null;

            RestCommand command = new RestCommand(
                new Uri(url),
                RestTransport.Get);

            command.Parameters.Add("kind", "album");

            return Invoke(command);
        }
    }
}
